package jmine.tec.proxy.javassist;

import javassist.util.proxy.ProxyFactory;
import jmine.tec.proxy.AbstractProxyBuilder;
import jmine.tec.proxy.ProxyBuilder;
import jmine.tec.proxy.chain.ChainElement;

/**
 * @author MarceloT
 */
public class JavassistProxyBuilder extends AbstractProxyBuilder implements ProxyBuilder {

    private final ProxyFactory proxyFactory = new ProxyFactory();

    private Object delegate;

    private ChainElement[] chainElements = new ChainElement[0];

    /**
     * @return Object
     */
    public Object build() {
        ChainedMethodHandler handler = new ChainedMethodHandler(delegate, chainElements);
        proxyFactory.setHandler(handler);
        proxyFactory.setInterfaces(this.collectAllInterfaces());
        try {
            return proxyFactory.createClass().newInstance();
        } catch (InstantiationException e) {
            throw new IllegalArgumentException(e);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * @param elements the elements
     */
    public void setChainElements(ChainElement... elements) {
        this.chainElements = elements;
    }

    /**
     * @param delegate the delegate
     */
    public void setDelegate(Object delegate) {
        if (delegate != null) {
            proxyFactory.setSuperclass(delegate.getClass());
            addInterfacesFrom(delegate.getClass());
        }
        this.delegate = delegate;
    }

    /**
     * @param type the type
     */
    @Override
    public void doSetMainType(Class<?> type) {
        if (type.isInterface()) {
            this.proxyFactory.setSuperclass(Object.class);
        } else {
            this.proxyFactory.setSuperclass(type);
        }

    }

}
